package com.hyxt.provider;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.hyxt.DTO.T809ServerHandler;
import com.hyxt.api.T809ServerService;
import com.hyxt.dao.RedisServiceDAO;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.HashMap;
import java.util.Map;

import static com.hyxt.DTO.T809ServerHandler.channelMap;

/**
 * @author shenp
 * @version v1.0
 * @Description;创建T809服务端
 * @Date: Create in 13:44 2017/11/22
 * @Modifide By:
 **/
@Service(interfaceClass = T809ServerService.class,version = "1.0.0")
public class T809ServerServiceImpl implements T809ServerService {
    /**
     * 日志
     */
    private static Log log = LogFactory.getLog(T809ServerServiceImpl.class);
    /**
     * redis对象
     */
    @Reference(version = "1.0.0")
    RedisServiceDAO redisServiceDAO;

    /**
     * 启动服务端
     * @param port 端口
     * @param mainOrBranch 主从标识（0：主；1：从）
     * @return
     */
    @Override
    public boolean startServer(Integer port, Integer mainOrBranch,Integer accessOrForward) {
        // NIO线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 1024)
                    .childHandler(new ChannelInitializer<io.netty.channel.Channel>() {
                        @Override
                        protected void initChannel(io.netty.channel.Channel arg0) throws Exception {
                            ChannelPipeline pipeline = arg0.pipeline();
                            pipeline.addLast("decoder",  new ByteArrayDecoder());
                            pipeline.addLast("encoder", new ByteArrayEncoder());
                            pipeline.addLast("handler", new T809ServerHandler(mainOrBranch,redisServiceDAO,accessOrForward));
                        }
                    });
            // 绑定端口,同步等待成功 绑定监听端口，f --> 类似于Future 用于异步操作的通知回调
            ChannelFuture f = bootstrap.bind(port).sync();
            log.info("T809服务端启动成功");
        }catch (Exception e){
            log.info("T809服务端启动失败");
            return false;
        }
        return true;
    }

    @Override
    public boolean deleteChannel(Integer sign, Integer mainOrBranch) {
        //获取ip+端口
        String ipAndPort = findIpAndPort(sign,mainOrBranch);
        //获取链路
        Channel channel = channelMap.get(ipAndPort);
        //删除redis中的对应关系
        redisServiceDAO.delete(sign+mainOrBranch+"",0);
        //删除缓存中的链路
        channelMap.remove(ipAndPort);
        if (!(channel==null)){
            channel.close();
        }
        return true;
    }

    public Channel findChannle(Integer sign, Integer mainOrBranch) {
        String ipAndPort = findIpAndPort(sign,mainOrBranch);
        if (channelMap.containsKey(ipAndPort)){
            //关闭链路
            return channelMap.get(ipAndPort);
        }
        return null;
    }

    @Override
    public boolean sendMessage(Integer sign, Integer mainOrBranch, byte[] bytes) {
        //查找链路
        Channel channel = findChannle(sign,mainOrBranch);
        if (!(channel==null)){
            //发送数据
            channel.writeAndFlush(bytes);
            return true;
        }
        return false;
    }

    /**
     * 从redis中查找对应标识的ip+port
     * @return
     */
    public String findIpAndPort(Integer sign, Integer mainOrBranch){
        Map<String,String> map = new HashMap<String,String>();
        //从redis中获取对应关系
        map = redisServiceDAO.getMap(sign+mainOrBranch+"",0);
        //获取ip+端口
        return map.get("ip");
    }

}

